package com.tom.demo.service.system.impl;

import cn.hutool.core.lang.Snowflake;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tom.demo.common.entity.SysRole;
import com.tom.demo.common.entity.SysUser;
import com.tom.demo.common.entity.SysUserRole;
import com.tom.demo.common.enumeration.FileUploadEnum;
import com.tom.demo.common.enumeration.ResponseEnum;
import com.tom.demo.common.exception.CustomException;
import com.tom.demo.common.response.Result;
import com.tom.demo.common.utils.SecurityUtils;
import com.tom.demo.component.MinioComponent;
import com.tom.demo.dto.AssignUserRoleDto;
import com.tom.demo.dto.UserEditDto;
import com.tom.demo.dto.UserDto;
import com.tom.demo.dto.UserPasswordDto;
import com.tom.demo.mapper.SysDeptMapper;
import com.tom.demo.mapper.SysRoleMapper;
import com.tom.demo.mapper.SysUserMapper;
import com.tom.demo.mapper.SysUserRoleMapper;
import com.tom.demo.service.system.UserService;
import com.tom.demo.vo.AssignUserRoleVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class UserServiceImpl implements UserService {
    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private SysDeptMapper sysDeptMapper;

    @Resource
    private MinioComponent minioComponent;

    @Value("${bucketName}")
    private String bucketName;

    @Resource
    private Snowflake snowflake;

    @Resource
    private SysUserRoleMapper sysUserRoleMapper;

    @Resource
    private SysRoleMapper sysRoleMapper;


    @Override
    public Result updatePassword(UserPasswordDto userPasswordDto) {

        //获取当前登录用户的id
        String userId = SecurityUtils.getLoginUserId();
        if(SecurityUtils.isAdmin(userId)){
            return Result.error("超级管理员不可以修改密码");
        }
        String oldPassword = userPasswordDto.getOldPassword();
        String newPassword = userPasswordDto.getNewPassword();
        SysUser sysUser = sysUserMapper.selectByPrimaryKey(userId);
        if(sysUser == null){
            return Result.error("未找到该用户");
        }

        //对比传过来的旧密码和数据库中的新密码是否匹配
        if(!SecurityUtils.matchesPassword(oldPassword,sysUser.getPassword())){
            return Result.error("旧密码不正确");
        }
        sysUser.setPassword(SecurityUtils.encryptPassword(newPassword));
        int i = sysUserMapper.updateByPrimaryKey(sysUser);
        return i > 0 ? Result.success():Result.error("修改密码失败");
    }

    @Override
    public Result pageList(Integer page, Integer pageSize, UserDto userDto) {
        String deptId = userDto.getDeptId();
        if(StringUtils.hasText(deptId)){
            Set<String> ids = new HashSet<>();
            ids.add(deptId);
            //这里先去递归出来需要的子集的部门deptId
            Set<String> deptIds = sysDeptMapper.findByDeptIdDownward(deptId);
            ids.addAll(deptIds);
            userDto.setDeptIds(ids);
        }
        PageHelper.startPage(page,pageSize);
        List<SysUser> sysUsers = sysUserMapper.pageList(userDto);
        PageInfo<SysUser> pageInfo = new PageInfo<>(sysUsers);
        return Result.success(pageInfo);
    }

    @Override
    @Transactional
    public Result insertUser(UserEditDto userEditDto) {
        MultipartFile multipartFile = userEditDto.getAvatarFile();
        String contentType = multipartFile.getContentType();
        // 校验文件格式
        if (!multipartFile.isEmpty() && !FileUploadEnum.AvatarEnum.isValidFormat(contentType)) {
            throw new CustomException(ResponseEnum.FILE_CONTENT_TYPE_ERROR);
        }
        //账号不能重复
        int usernameCount =  sysUserMapper.findOne(userEditDto.getUsername(),null,null,null);
        if(usernameCount>0){
            throw new CustomException(ResponseEnum.USERNAME_DATA_EXIST);
        }
        //邮箱不能重复
        int emailCount =  sysUserMapper.findOne(null,userEditDto.getEmail(),null,null);
        if(emailCount>0){
            throw new CustomException(ResponseEnum.EMAIL_DATA_EXIST);
        }
        //手机号不能重复
        int phoneNumberCount =  sysUserMapper.findOne(null,null,userEditDto.getPhoneNumber(),null);
        if(phoneNumberCount>0){
            throw new CustomException(ResponseEnum.PHONE_NUMBER_DATA_EXIST);
        }
        //原始文件名称
        try {
            String url = minioComponent.uploadFile(bucketName, multipartFile);
            SysUser sysUser = new SysUser();
            BeanUtils.copyProperties(userEditDto, sysUser);
            //设置userId
            sysUser.setUserId(snowflake.nextIdStr());
            sysUser.setPassword("123456");
            //对密码进行加密
            sysUser.setPassword(SecurityUtils.encryptPassword(sysUser.getPassword()));
            sysUser.setAvatar(url);
            sysUser.setCreateBy(SecurityUtils.getLoginUser().getUsername());
            sysUser.setCreateTime(new Date());
            sysUserMapper.insert(sysUser);
        } catch (Exception e) {
            log.error("头像上传minio服务器失败");
            throw new RuntimeException(e);
        }
        return Result.success();
    }

    @Override
    public Result updateUserStatus(String userId, Boolean status) {
        SysUser sysUser = sysUserMapper.selectByPrimaryKey(userId);
        sysUser.setStatus(status);
        sysUser.setUpdateBy(SecurityUtils.getLoginUserName());
        sysUser.setUpdateTime(new Date());
        int row = sysUserMapper.updateByPrimaryKey(sysUser);
        return row > 0 ? Result.success():Result.error("修改状态失败");
    }

    @Override
    public Result findByUserId(String userId) {
        SysUser sysUser = sysUserMapper.selectByPrimaryKey(userId);
        return Result.success(sysUser);
    }

    @Override
    @Transactional
    public Result deleteByUserId(String userId) {
        //删除用户
        int row = sysUserMapper.deleteByPrimaryKey(userId);
        //删除用户和角色的关联关系
        sysUserRoleMapper.deleteByUserId(userId);
        return row>0?Result.success():Result.error("删除用户失败");
    }

    @Override
    @Transactional
    public Result updateUser(UserEditDto userEditDto) throws Exception {
        String userId = userEditDto.getUserId();
        if(!StringUtils.hasText(userId)){
            return Result.error("用户id不能为空");
        }
        SysUser sysUser = sysUserMapper.selectByPrimaryKey(userId);
        MultipartFile multipartFile = userEditDto.getAvatarFile();

        // 校验文件格式
        if (multipartFile != null && !multipartFile.isEmpty()) {
            if(!FileUploadEnum.AvatarEnum.isValidFormat(multipartFile.getContentType())){
                throw new CustomException(ResponseEnum.FILE_CONTENT_TYPE_ERROR);
            }
            String url = minioComponent.uploadFile(bucketName, multipartFile);
            sysUser.setAvatar(url);

        }
        //账号不能重复
        int usernameCount =  sysUserMapper.findOne(userEditDto.getUsername(),null,null,userId);
        if(usernameCount>0){
            throw new CustomException(ResponseEnum.USERNAME_DATA_EXIST);
        }
        //邮箱不能重复
        int emailCount =  sysUserMapper.findOne(null,userEditDto.getEmail(),null,userId);
        if(emailCount>0){
            throw new CustomException(ResponseEnum.EMAIL_DATA_EXIST);
        }
        //手机号不能重复
        int phoneNumberCount =  sysUserMapper.findOne(null,null,userEditDto.getPhoneNumber(),userId);
        if(phoneNumberCount>0){
            throw new CustomException(ResponseEnum.PHONE_NUMBER_DATA_EXIST);
        }

        BeanUtils.copyProperties(userEditDto, sysUser);
        //对密码进行加密
        sysUser.setPassword(SecurityUtils.encryptPassword(sysUser.getPassword()));
        sysUser.setUpdateBy(SecurityUtils.getLoginUser().getUsername());
        sysUser.setUpdateTime(new Date());
        sysUserMapper.updateByPrimaryKey(sysUser);
        return Result.success();
    }

    @Override
    public Result toAssign(String userId) {
        AssignUserRoleVo assignUserRoleVo = new AssignUserRoleVo();
        //这里我们需要查询所有角色列表和当前用户所属的角色列表
        //1:查询所有的角色，返回的是一个角色集合
        List<SysRole> sysRoleList =  sysRoleMapper.selectAll();
        //2:查询当前角色当前所属的角色roleId集合
        List<String> roleIds = sysUserRoleMapper.selectByUserId(userId);
        List<SysRole> prepossessRoles;
        if(!CollectionUtils.isEmpty(roleIds)){
            prepossessRoles = sysRoleMapper.findByRoleIds(roleIds);
        }else {
            prepossessRoles = new ArrayList<>();
        }
        assignUserRoleVo.setAllRoles(sysRoleList);
        assignUserRoleVo.setPrepossessRoles(prepossessRoles);
        return Result.success(assignUserRoleVo);
    }

    @Override
    @Transactional
    public Result doAssign(AssignUserRoleDto assignUserRoleDto) {
        String userId = assignUserRoleDto.getUserId();
        //先去删除原来用户绑定的角色
        sysUserRoleMapper.deleteByUserId(userId);
        //然后插入新的用户id和角色id的绑定关系
        List<String> roleIds = assignUserRoleDto.getRoleIds();
        List<SysUserRole> sysUserRoles = roleIds.stream().map(roleId -> {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(userId);
            sysUserRole.setRoleId(roleId);
            return sysUserRole;
        }).collect(Collectors.toList());
        if(!CollectionUtils.isEmpty(sysUserRoles)){
            sysUserRoles.forEach(sysUserRole -> {
                sysUserRoleMapper.insert(sysUserRole);
            });
        }
        return Result.success();
    }

    @Override
    public Result getUserOptions() {
        List<SysUser> sysUserList = sysUserMapper.selectAll();
        return Result.success(sysUserList);
    }
}
